//实现 pow(x, n) ，即计算 x 的 n 次幂函数（即，xⁿ ）。 
//
// 
//
// 示例 1： 
//
// 
//输入：x = 2.00000, n = 10
//输出：1024.00000
// 
//
// 示例 2： 
//
// 
//输入：x = 2.10000, n = 3
//输出：9.26100
// 
//
// 示例 3： 
//
// 
//输入：x = 2.00000, n = -2
//输出：0.25000
//解释：2-2 = 1/22 = 1/4 = 0.25
// 
//
// 
//
// 提示： 
//
// 
// -100.0 < x < 100.0 
// -231 <= n <= 231-1 
// -104 <= xⁿ <= 104 
// 
// Related Topics 递归 数学 👍 974 👎 0

package leetcode.editor.cn;
//leetcode submit region begin(Prohibit modification and deletion)
class Solution50 {

    public double myPow(double x, int n){
        long b = n; //b=-2147483648（2的31次方-1）时出错
        return n < 0 ? quickMul2(1/x,-b):quickMul2(x,n);
    }

    private double quickMul2(double x, long n) {
        double ans = 1.0;
        while(n > 0){
            if((n&1) == 1){
                ans *= x;
            }
            x *= x; //将贡献不断地平方
            n >>>= 1; //n减半
        }
        return ans;
    }

    /**
     * 快速幂+递归的优化
     *
     * 时间复杂度：o(log(n)),即为递归的层数。
     * 空间复杂度：o(log(n)),即为递归的层数。这是由于递归的函数调用会使用栈空间。
     * @param x
     * @param n
     * @return
     */
    public double myPow3(double x, int n){
        return n < 0 ? 1/quickMul1(x,n):quickMul1(x,n);
    }

    private double quickMul1(double x, int n) {
        if(n == 0){
            return 1;
        }
        double res = quickMul1(x, n/2);
        return n % 2 == 0 ? res*res : x*res*res;
    }

    /**
     * 快速幂+递归,超时
     * 时间复杂度：o(n)
     * 空间复杂度：o(n)
     * @param x
     * @param n
     * @return
     */
    public double myPow2(double x, int n){
        return n < 0 ? 1/quickMul(x,n):quickMul(x,n);
    }

    public double quickMul(double x, int n){
        if(n == 0){
            return 1;
        }
        return n % 2 == 0 ? quickMul(x,n/2)*quickMul(x,n/2) : x*quickMul(x,n/2)*quickMul(x,n/2);
    }

    /**
     * 递归，栈溢出
     */
    double result = 0;
    public double myPow1(double x, int n) {
        result = x;
        if( n < 0){
            n = -n;
            return 1/traversal(x, n, 1);
        } else if(n>0){
            return traversal(x, n, 1);
        }  else return 1;
    }

    public double traversal(double x, int n, int i){
        if(i >= n){
            return result;
        }
        double res = result * traversal(x, n, i+1);
        return res;
    }
}
//leetcode submit region end(Prohibit modification and deletion)
